package org.xukai.common.util.xml;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xukai
 * @desc
 * @date 2016-12-20-上午 10:28
 */
public class XmlUtils {

    private static final Logger LOG = LoggerFactory.getLogger(XmlUtils.class);
    private static Map<Class, JAXBContext> jaxbContextMap = new HashMap<Class, JAXBContext>();

    public static <T> String toRequestXML(T t, Class<T> clazz) {
        try {
            Marshaller marshaller = getMarshaller(clazz);
            StringWriter sw = new StringWriter();
            marshaller.marshal(t, sw);
            return sw.toString();
        } catch (Exception e) {
            LOG.error("toRequestXML 异常", e);
            return null;
        }
    }

    public static <T> String toRequestXML(T t, Class<T> clazz, boolean headerFlag, String encoding) {
        try {
            Marshaller marshaller = getMarshaller(clazz);
            StringWriter sw = new StringWriter();
            if (!headerFlag) { // xml是否需要head
                marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            }
            if (encoding != null && !"".equals(encoding)) { // 默认的encoding
                // 是UTF-8
                marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
            }

            marshaller.marshal(t, sw);
            return sw.toString();
        } catch (Exception e) {
            LOG.error("toRequestXML 异常", e);
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T toResponseObject(Class<T> clazz, String xml) {
        try {
            if (StringUtils.isEmpty(xml)) {
                return null;
            }
            Unmarshaller unMarshaller = getUnmarshaller(clazz);
            return (T) unMarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            LOG.error("toResponseObject 异常传入xml:" + xml, e);
            return null;
        }
    }

    private static Marshaller getMarshaller(Class clazz) throws Exception {
        JAXBContext context = getJAXBContext(clazz);
        Marshaller marshaller = context.createMarshaller();
        return marshaller;
    }

    private static Unmarshaller getUnmarshaller(Class clazz) throws Exception {
        JAXBContext context = getJAXBContext(clazz);
        Unmarshaller unMarshaller = context.createUnmarshaller();
        return unMarshaller;
    }

    private static JAXBContext getJAXBContext(Class clazz) throws Exception {
        JAXBContext jaxbContext = jaxbContextMap.get(clazz);
        if (jaxbContext != null) {
            return jaxbContext;
        }
        jaxbContext = JAXBContext.newInstance(clazz);
        jaxbContextMap.put(clazz, jaxbContext);
        return jaxbContext;
    }
}
